package org.unitils.jmock;

import static org.unitils.util.AnnotationUtils.getFieldsAnnotatedWith;
import static org.unitils.util.ReflectionUtils.setFieldValue;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Properties;

import org.jmock.Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.unitils.core.Module;
import org.unitils.core.TestListener;
import org.unitils.jmock.annotation.Jmock;

public class JmockModule implements Module {

	private Mockery context;

	public TestListener createTestListener() {
		return new JmockTestListener();
	}

	public void init(Properties configuration) {
		// TODO Auto-generated method stub
	}

	public Mockery getMockery() {
		return this.context;
	}

	private void createAndInjectMocksIntoTest(Object testObject) {
		List<Field> mockFields = getFieldsAnnotatedWith(testObject.getClass(), Jmock.class);
		for (Field mockField : mockFields) {

			Class<?> mockType = mockField.getType();

			// Mock mockAnnotation = mockField.getAnnotation(Mock.class);
			Object mockObject = context.mock(mockType);
			setFieldValue(testObject, mockField, mockObject);
		}
	}

	protected class JmockTestListener extends TestListener {
		@Override
		public void beforeTestSetUp(Object testObject) {
			context = new Mockery() {
				{
					setImposteriser(ClassImposteriser.INSTANCE);
				}
			};

			createAndInjectMocksIntoTest(testObject);
		}

		@Override
		public void afterTestMethod(Object testObject, Method testMethod, Throwable throwable) {
			context.assertIsSatisfied();
		}
	}
}
